#!/usr/bin/perl

use strict;
use warnings;

use List::Util qw(sum);

# external variables
our %Settings;

our %Messages;
our $OS_win;
our %ParameterRegExps;
our %ParameterRegExpValues;
our %GlobalHighlighter;
our @History;

our %Commands;
our %Aliases;
our %Separators;
our $LastCommandType;
our @LastResult;
our $Dirname;

our $CurrentPrompt;

my $HistoryPointer;
my $cipherKey = "3845307703096290674869301291068520826141172501386118369144311113210791127304530";

# init text printer
&setSimpleTXTOutput;

=encoding utf-8

=head1 NÉV/NAME

setVALAMIOutput - beállítja a mező és rekord szeparátorokat, az I<universalTextPrinter> számára

=head2 SYNOPSIS/SZINTAXIS

        &setSimpleTXTOutput();
        &universalTextPrinter( "KEY\tREGEXP\tVALUE", @array );


 
=head2 DESCREPTION/LEÍRÁS

A szubrutin a %Separators nevű hash-t tölti fel következő elemekkel:

        Iam              => Jeleneleg nem használt, pl.: "HTML", 
        startTable       => A táblázat indító eleme, pl.: "<table>\n", 
        stopTable        => A táblázat záró elemem, pl.: "</table>\n",
        startHeaderLine  => A fejléc sorainak indító eleme, pl.: "<tr>",
        stopHeaderLine   => A fejléc sorainak záró eleme, pl.: "</tr>\n",
        startHeaderField => A fejléc mezőinek indító eleme, pl.: "<th>",
        stopHeaderField  => A fejléc mezőinek záró eleme, pl.:"</th>",
        startField       => A táblázat mezőinek indító eleme, pl.: "<td>",
        stopField        => A táblázat mezőinek záró eleme, pl.: "</td>",
        startRecord      => A táblázat sorainak indító eleme, pl.: "<tr>",
        stopRecord       => A táblázat sorainak záró eleme, pl.: "</tr>\n",

=head2 AUTHOR/FEJLESZTŐ

Szabó Marcell

=head2 SEE ALSO/TOVÁBBI INFORMÁCIÓK

I<universalTextPrinter>

=cut

sub setHTMLOutput
{
    %Separators = (
                    Iam              => "HTML",
                    startTable       => "<table>\n",
                    stopTable        => "</table>\n",
                    startHeaderLine  => "<tr>",
                    stopHeaderLine   => "</tr>\n",
                    startHeaderField => "<th>",
                    stopHeaderField  => "</th>",
                    startField       => "<td>",
                    stopField        => "</td>",
                    startRecord      => "<tr>",
                    stopRecord       => "</tr>\n",
                  );
}

sub setCSVOutput
{

    %Separators = (
                    Iam              => "CSV-NOQUOTE",
                    startTable       => "",
                    stopTable        => "",
                    startHeaderLine  => "",
                    stopHeaderLine   => "\n",
                    startHeaderField => "",
                    stopHeaderField  => ";",
                    startField       => "",
                    stopField        => ";",
                    startRecord      => "",
                    stopRecord       => "\n",
                  )

}

sub setTXTOutput
{

    %Separators = (
                    Iam              => "TXT",
                    startTable       => "",
                    stopTable        => "",
                    startHeaderLine  => "|",
                    stopHeaderLine   => "\n",
                    startHeaderField => "",
                    stopHeaderField  => "|",
                    startField       => "",
                    stopField        => "|",
                    startRecord      => "|",
                    stopRecord       => "\n",
                  )

}

sub setSimpleTXTOutput
{

    %Separators = (
                    Iam              => "TXT",
                    startTable       => "",
                    stopTable        => "",
                    startHeaderLine  => "",
                    stopHeaderLine   => "\n",
                    startHeaderField => "",
                    stopHeaderField  => " ",
                    startField       => "",
                    stopField        => " ",
                    startRecord      => "",
                    stopRecord       => "\n",
                  );
}

sub setTestTXTOutput
{

    %Separators = (
                    Iam              => "TXT",
                    startTable       => "STAT",
                    stopTable        => "STOT",
                    startHeaderLine  => "STAH",
                    stopHeaderLine   => "STOH\n",
                    startHeaderField => "STAHF",
                    stopHeaderField  => "STOHF ",
                    startField       => "STAF",
                    stopField        => "STOF ",
                    startRecord      => "STAR",
                    stopRecord       => "STOR\n",
                  );
}

sub universalTextPrinter ( @ )
{
    if ( $ParameterRegExpValues{HTML} ) { &HTMLPrinter(@_); return }

    my @result = @_;
    my $i      = 0;

    my $startTable       = $Separators{startTable};
    my $stopTable        = $Separators{stopTable};
    my $startHeaderLine  = $Separators{startHeaderLine};
    my $stopHeaderLine   = $Separators{stopHeaderLine};
    my $startHeaderField = $Separators{startHeaderField};
    my $stopHeaderField  = $Separators{stopHeaderField};
    my $startField       = $Separators{startField};
    my $stopField        = $Separators{stopField};
    my $startRecord      = $Separators{startRecord};
    my $stopRecord       = $Separators{stopRecord};

    my @fieldlength;
    my @fieldFormat;
    my @fieldColor;
    my @fieldHeader;
    my @fieldAlign;

    &updateTerminalSettings;

    # Header Reader
    my $j = 0;
    my @header = split( /\t/, $result[0] );
    splice( @result, 0, 1 );

    foreach my $field (@header)
    {
        my ( $format, $color, $header, $align );
        if   ( $field =~ s/{\s*([^\}]*?)\s*}// ) { $format = $1; }
        else                                     { $format = ""; }
        if   ( $field =~ s/\[\s*([^\]]*?)\s*\]// ) { $color = $1 }
        else                                       { $color = ""; }
        $field =~ s/^\s*|\s*$//g;
        $header = $field;
        if (uc($format) =~ m/LEFT|RIGHT/ ) {
            $align = $format;
            $format = "";
        } else {$align = "LEFT";}
        $fieldlength[$j] = &colorLength($field);
        $fieldColor[$j]  = $color;
        $fieldHeader[$j] = $header;
        $fieldFormat[$j] = $format;
        $fieldAlign[$j]  = $align;
        $j++;
    }

    # Find longest fields
    foreach (@result)
    {
        chomp;
        my @line = split( /\t/, $_ );
        $j = 0;
        foreach (@line)
        {
            if ( $fieldFormat[$j] !~ m/MAX/ )
            {
                my $printableField = $_;
                $printableField = sprintf( $fieldFormat[$j], $_ )
                  if ( $fieldFormat[$j] ne "" );
                $fieldlength[$j] = &colorLength($printableField)
                  if ( $fieldlength[$j] < &colorLength($printableField) );
            }
            $j++;
        }
    }

    $j = 0;


    # Find the MAX in the format field
    foreach my $field (@fieldlength)
    {
        my $remained = $Settings{TERMINALCOLS} - sum(@fieldlength);
        my $max =
          $fieldlength[$j] +
          $remained -
          ( colorLength($startRecord) +
            colorLength($stopRecord) +
            $#header * &colorLength($startField) +
            $#header * &colorLength($stopField) +
            &colorLength($stopField) +
            &colorLength($stopRecord) +
            1 );
        if ( $fieldFormat[$j] =~ m/MAX/ && $max <= $fieldlength[$j] )
        {
            &msg("0017E");    ##Terminal width is too small!
            $max = 1;
        }

        if ( $fieldFormat[$j] =~ s/MAX/$max/g )
        {
            $fieldlength[$j] = $max;
        }
        $j++;

    }

    # A printelendö szöveg összeállítása
    my @toPrint;
    my $printableLine  = $startHeaderLine;
    my $printableField = "";
    my $header_line    = $startHeaderLine;

    $j = 0;
    #HEADER
    foreach (@fieldHeader)
    {
        chomp;
        $printableField = $_;

            if ( $fieldAlign[$j] ne "LEFT" )
            {
                $printableField = sprintf( "% " . (length( $printableField )+$fieldlength[$j]-&colorLength( $printableField ) ) . "s", "$printableField" );
            }
            else
            {
                $printableField = sprintf( "%-" . (length( $printableField )+$fieldlength[$j]-&colorLength( $printableField ) ) . "s", "$printableField" );
            }

        if ( $Settings{HEADERCOLOR} eq "" )
        {
            $Settings{HEADERCOLOR} = $fieldColor[$j];
        }
        
        $printableField = colorString( $printableField, $Settings{HEADERCOLOR} );
        $header_line .=
            $startHeaderField
          . colorString( "-" x $fieldlength[$j], $Settings{HEADERCOLOR} )
          . $stopHeaderField;
        $printableLine .= $startHeaderField . $printableField . $stopHeaderField;
        #print $printableLine;
        $j++;
    }
    

    # and finally add the lines around the header

      if ( "@fieldHeader" !~ m/NOHEADER/ ) {
        push( @toPrint, $startTable );
        push( @toPrint, $header_line . $stopHeaderLine);
        push( @toPrint, $printableLine . $stopHeaderLine);
        push( @toPrint, $header_line . $stopHeaderLine );
      }

    #BODY
    foreach (@result)
    {
        chomp;
        my @line = split( /\t/, $_ );
        my $j = 0;
        my $beforeLast      = "" ;
        my $beforeLastEmpty = "" ;
        my $last = "";
        $printableLine = "";
        foreach (@line)
        {
            $printableField = $_;

            $printableField = globalHighlighter( $printableField );


            if ( $fieldAlign[$j] ne "LEFT" )
            {
                $printableField = sprintf( "% " . (length( $printableField )+$fieldlength[$j]-&colorLength( $printableField ) ) . "s", "$printableField" );
            }
            else
            {
                $printableField = sprintf( "%-" . (length( $printableField )+$fieldlength[$j]-&colorLength( $printableField ) ) . "s", "$printableField" );
            }

#			if ($printableField =~ m/$grep/ ) {$printableField = colorString($printableField,"RED");} ## whole line grep
#			if ($printableField =~ m/$grep/ ) {my $cgrep = colorString($grep,"RED") ;$printableField =~ s/$grep/$cgrep/;} ## highlighter GREP
            if (    defined( $ParameterRegExpValues{HIGHLIGHT} )
                 && $ParameterRegExpValues{HIGHLIGHT} ne ""
                 && $printableField =~ m/$ParameterRegExpValues{HIGHLIGHT}/ )
            {

                #				my $chighlighter = sprintf (colorString($1,"RED"));
                my $chighlighter =
                  &colorString( $ParameterRegExpValues{HIGHLIGHT}, $Settings{HIGHLIGHTCOLOR} );

                $printableField =~ s/$ParameterRegExpValues{HIGHLIGHT}/$chighlighter/;
            }    ## highlighter grep

            $printableField = &colorString( $printableField, $fieldColor[$j] );

            #print "hossz: ".length($printableField);
            $printableLine .= $startField . $printableField . $stopField;
            if ($j == $#line) { $last = $startField . $printableField . $stopField }
            $j++;
            if ($j == $#line) { $beforeLast = $printableLine };
            if ($j <= $#line) { $beforeLastEmpty .= $startField . sprintf( "%-" . &colorLength( $printableField ) . "s", "" ) . $stopField }
        }
        if ( &colorLength( $startRecord . $printableLine . $stopRecord ) > $Settings{TERMINALCOLS} && 1 )
        {        #Hosszu sorok szopasa
            $last =~ s/\s+$//;
            #print "BefLAST: [$beforeLast]\n";
            #print "LAST: [$last]\n";
            my $restLength = $Settings{TERMINALCOLS} -  ( $OS_win ? 1 : 0 ) - &colorLength($beforeLast.$startRecord.$stopRecord.$stopField);
            #my $printable = $beforeLast.substr( $last, 0, &colorSubstr( $last, $restLength )).$stopField.$stopRecord;
            my $rest = $last; #substr( $last, $restLength );
            my $currentPos = $restLength;
            #print "restLength: [$restLength]\n";

            my $inheritLastColor = "";

            #print $rest;
            #push( @toPrint, $startRecord . $printable . $stopRecord );
            my $c = 0;
            while ( 1 ) {

                #print $startRecord.$beforeLast.$startField.substr ($rest, 0, &colorSubstr($rest, $restLength)).$stopField.$stopRecord;
                #print "length: ".&colorLength($rest)."[".$rest."]"."\n";

                if ( $c == 0 ) {
                	$c++;
                }
                else {
                    $beforeLast = $beforeLastEmpty;
                }

                if ( &colorLength($rest) < $restLength ) {
                	push( @toPrint, $startRecord.$beforeLast.$startField.$inheritLastColor.substr( $rest, 0, &colorSubstr( $rest, &colorLength($rest) ) ).&colorString( "", "RESET" ).$stopRecord );
                	last;
                }
                else {
                    push( @toPrint, $startRecord.$beforeLast.$startField.$inheritLastColor.substr( $rest, 0, &colorSubstr( $rest, $restLength ) ).&colorString( "", "RESET" ).$stopField.$stopRecord );
                    my $tmp = substr( $rest, 0, &colorSubstr( $rest, $restLength ) );
                    $inheritLastColor = $1 if ( $tmp =~ s/(\e\[\d+?;*\d*m)//g );
                }

                $rest = substr( $rest, &colorSubstr( $rest, $restLength ) );

            }
           } else {
               push( @toPrint, $startRecord . $printableLine . $stopRecord );
           }
        #print $printableLine."\n";
        #print @toPrint;
        #exit;
    }
    push( @toPrint, $stopTable );

    ### Printing to the screen
    my $more = 1;    ## MORE
    foreach (@toPrint)
    {
        if (&colorLength($_) > ( $Settings{TERMINALCOLS}) ) {
            print substr( $_, 0, &colorSubstr( $_, $Settings{TERMINALCOLS} - &colorLength( $stopField.$stopRecord ) - ( $OS_win ? 1 : 0 ) )).$stopField.$stopRecord.&colorString( "", "RESET" );
        } else {
            print $_;
        }
        if (    $ParameterRegExpValues{MORE}
             && $Settings{TERMINALROWS} - 2 <= $more )
        {
            print "more...   (<ENTER> to continue, 'C' to cancel)";
            last if ( <STDIN> =~ m/c/i );
            $more = 0;
        }
        $more++;
    }
    ### Printing to a file if needed
    if ( defined( $ParameterRegExpValues{OUTPUT} )
         && $ParameterRegExpValues{OUTPUT} ne "" )
    {
        open my $OUTFILE, ">$ParameterRegExpValues{OUTPUT}" or die;
        print $OUTFILE @toPrint;
        close $OUTFILE or die;
    }
    if ( defined( $ParameterRegExpValues{MAIL} )
         && $ParameterRegExpValues{MAIL} ne "" )
    {
        &sendMail( $ParameterRegExpValues{MAIL}, @toPrint );
    }

    # reset the settings
    &setSimpleTXTOutput();
    $Settings{'DISABLEGREP'} = 0;

}

sub updateTerminalSettings
{
    if ($OS_win)
    {

        # MS Windows environments
        my $CONSOLE = new Win32::Console;
        (
           $Settings{TERMINALCOLS},      $Settings{TERMINALROWS},
           $Settings{TERMINALCURSORCOL}, $Settings{TERMINALCURSORROW}
        ) = $CONSOLE->Info();
    }
    else
    {

        # UNIX like environments
        (
           $Settings{TERMINALCOLS},      $Settings{TERMINALROWS},
           $Settings{TERMINALCURSORCOL}, $Settings{TERMINALCURSORROW}
        ) = GetTerminalSize();
    }
    &msg("0017E") if ( $Settings{TERMINALCOLS} < 80 );
    # &msg( "0010D", $Settings{TERMINALCOLS}, $Settings{TERMINALROWS} );
}

sub HTMLPrinter ( @ )
{    #
    &setHTMLOutput;
    $ParameterRegExpValues{NOCOLOR} = 1;
    my @result = @_;

    my $startTable       = $Separators{startTable};
    my $stopTable        = $Separators{stopTable};
    my $startHeaderLine  = $Separators{startHeaderLine};
    my $stopHeaderLine   = $Separators{stopHeaderLine};
    my $startHeaderField = $Separators{startHeaderField};
    my $stopHeaderField  = $Separators{stopHeaderField};
    my $startField       = $Separators{startField};
    my $stopField        = $Separators{stopField};
    my $startRecord      = $Separators{startRecord};
    my $stopRecord       = $Separators{stopRecord};

    my @fieldColor;
    my @fieldHeader;

    # Header Reader
    my $j = 0;
    my @header = split( /\t/, $result[0] );
    splice( @result, 0, 1 );

    foreach my $field (@header)
    {    #text  =~ s/\[\s*([^\]]*?)\s*\]//;
        my ( $format, $color, $header );
        if   ( $field =~ s/\[\s*([^\]]*?)\s*\]// ) { $color = $1 }
        else                                       { $color = ""; }
        $field =~ s/^\s*|\s*$//g;
        $header = $field;

        $fieldColor[$j]  = $color;     #print "$j.oszlop szin:   $fieldColor[$j]\n";
        $fieldHeader[$j] = $header;    #print "$j.oszlop header: $fieldHeader[$j]\n";
        $j++;
    }

    # A printelendö szöveg összeállítása
    my @toPrint;
    my $printableLine  = $startHeaderLine;
    my $printableField = "";
    my $header_line    = $startHeaderLine;

    $j = 0;

    #HEADER
    foreach (@fieldHeader)
    {
        chomp;
        $printableField = $_;

        if ( $Settings{HEADERCOLOR} eq "" )
        {
            $Settings{HEADERCOLOR} = $fieldColor[$j];
        }
        $printableField = &colorHTMLtag( $printableField, $Settings{HEADERCOLOR} );
        $header_line .= "";    #$startHeaderField$stopHeaderField ;
        $printableLine .= $startHeaderField . $printableField . $stopHeaderField;

        $j++;
    }

    # and finally add the lines around the header
    push( @toPrint, $startTable );

#push ( @toPrint, $header_line.$stopHeaderLine.$printableLine.$stopHeaderLine.$header_line.$stopHeaderLine ) if ( "@fieldHeader" !~ m/NOHEADER/ );
    push( @toPrint, $printableLine . $stopHeaderLine )
      if ( "@fieldHeader" !~ m/NOHEADER/ );

#BODY
#	@result = grep(/$ParameterRegExpValues{GREP}/i, @result)  if  (defined ($ParameterRegExpValues{GREP}) && $ParameterRegExpValues{GREP} ne "" && $Settings{'DISABLEGREP'} eq 'OFF'); ## Grep
#	@result = grep(!/$ParameterRegExpValues{INVGREP}/i, @result)  if  (defined ($ParameterRegExpValues{INVGREP}) && $ParameterRegExpValues{INVGREP} ne "" && $Settings{'DISABLEGREP'} eq 'OFF'); ## INVGrep
    foreach (@result)
    {
        chomp;
        my @line = split( /\t/, $_ );
        my $j = 0;
        $printableLine = "";
        foreach (@line)
        {
            $printableField = $_;

            if (    defined( $ParameterRegExpValues{HIGHLIGHT} )
                 && $ParameterRegExpValues{HIGHLIGHT} ne ""
                 && $printableField =~ m/$ParameterRegExpValues{HIGHLIGHT}/ )
            {
                my $chighlighter =
                  &colorHTMLtag( $ParameterRegExpValues{HIGHLIGHT}, $Settings{HIGHLIGHTCOLOR} );
                $printableField =~ s/$ParameterRegExpValues{HIGHLIGHT}/$chighlighter/;
            }    ## highlighter grep

            $printableField = &colorHTMLtag( $printableField, $fieldColor[$j] );

            #print "hossz: ".length($printableField);
            $printableLine .= $startField . $printableField . $stopField;
            $j++;
        }
        push( @toPrint, $startRecord . $printableLine . $stopRecord );
    }
    push( @toPrint, $stopTable );

    ### Printing to the screen
    foreach (@toPrint)
    {
        print $_;
    }
    ### Printing to a file if needed
    if ( defined( $ParameterRegExpValues{OUTPUT} )
         && $ParameterRegExpValues{OUTPUT} ne "" )
    {
        open my $OUTFILE, ">$ParameterRegExpValues{OUTPUT}" or die;
        print $OUTFILE @toPrint;
        close $OUTFILE or die;
    }

#	if (defined ($ParameterRegExpValues{MAIL}) && $ParameterRegExpValues{MAIL} ne "") {&sendMail($ParameterRegExpValues{MAIL},@toPrint);}

}

sub colorHTMLtag()
{
    my $string = $_[0];
    my $color  = $_[1];

    if ( !$ParameterRegExpValues{NOCOLOR} && $color ne "" )
    {
        return "<FONT COLOR=\"$color\">" . $string . "</FONT>";
    }
    else
    {
        return $string;
    }
}

sub setServer($)
{

    &msg( "0004D", "setServer" );
    if (    !defined( $_[0] )
         || $_[0] =~ m/default$|defaul$|defau$|defa$|def$/i
         || $_[0] eq "" )
    {
        $Settings{SERVER} = $Settings{DEFAULTSERVER};
    }
    else
    {
        my $server = uc( $_[0] );
        if ($OS_win)
        {
            if ( $_[0] =~ m/(\S*)\/(\S*)@(\S*):(\d*)/i )
            {
                $Settings{'INLINE[TSMUSERNAME]'} = $1;
                $Settings{'INLINE[TSMPASSWORD]'} = $2;
                $Settings{'INLINE[TSMSERVER]'}   = $3;
                $Settings{'INLINE[TSMPORT]'}     = $4;
                $Settings{'SERVER'}              = "INLINE";
            }
            else
            {
                $Settings{SERVER} = $server;
            }
        }
        else
        {
            if ( $_[0] =~ m/(\S*)\/(\S*)@(\S*)/i )
            {
                $Settings{'INLINE[TSMUSERNAME]'} = $1;
                $Settings{'INLINE[TSMPASSWORD]'} = $2;
                $Settings{'INLINE[TSMSERVER]'}   = $3;
                $Settings{'SERVER'}              = "INLINE";
                return 0;
            }
            else
            {
                $Settings{SERVER} = $server;
            }

        }
    }
    my $TSMUserName = $Settings{SERVER} . "[TSMUSERNAME]";
    my $TSMPassword = $Settings{SERVER} . "[TSMPASSWORD]";
    my $TSMServer   = $Settings{SERVER} . "[TSMSERVER]";
    my $TSMPort     = $Settings{SERVER} . "[TSMPORT]" if ( $OS_win);

    if (    !defined( $Settings{$TSMServer} )
         || !defined( $Settings{$TSMUserName} )
         || !defined( $Settings{$TSMPassword} ) )
    {
        &msg( "0015E", "$Settings{SERVER}" );
        $Settings{SERVER} = $Settings{DEFAULTSERVER};
        $TSMUserName      = $Settings{SERVER} . "[TSMUSERNAME]";
        $TSMPassword      = $Settings{SERVER} . "[TSMPASSWORD]";
        $TSMServer        = $Settings{SERVER} . "[TSMSERVER]";
        $TSMPort          = $Settings{SERVER} . "[TSMPORT]" if ( $OS_win);
    }
    &msg( "0009D", "$TSMUserName", "$Settings{$TSMUserName}" );
    &msg( "0009D", "$TSMPassword", "$Settings{$TSMPassword}" );
    &msg( "0009D", "$TSMServer",   "$Settings{$TSMServer}" );
    &msg( "0009D", "$TSMPort",     "$Settings{$TSMPort}" ) if ( $OS_win);
    if ( $Settings{SERVER} eq "" )
    {
        &msg( "0014I", "DEFAULT" );
    }
    else
    {
        &msg( "0014I", "$Settings{SERVER}" );
    }
    &msg( "0005D", "setServer", 0 );
    return 0;

}

sub checkPassword ()
{
    if ( !defined( $_[0] ) )
    {
        &msg( "0001E", "checkPassword" );
        return 1;
    }
    my $configfileOption = $_[0];
    open( my $CONFIGFILE, "<$configfileOption" )
      or die "File ($configfileOption) open error: $!";
    my @fileContent = <$CONFIGFILE>;
    close($CONFIGFILE);

    my @codedContent;
    my $changed = 0;
    foreach (@fileContent)
    {
        if (m/TSMPASSWORD/)
        {

            my ( $hash_key, $hash_value ) = split( /=/, $_, 2 );
            $hash_key   =~ s/^\s*|\s*$//g;
            $hash_value =~ s/^\s*|\s*$//g;
            if ( $hash_value =~ m/^XOR{/i ) { push( @codedContent, $_ ); next; }
            my $passwordLength = length($hash_value);
            my $cipher         = substr( $cipherKey, 0, $passwordLength );
            my $xor            = $hash_value ^ $cipher;
            push( @codedContent, "$hash_key = XOR{$xor}\n" );
            $changed = 1;
        }
        else
        {
            push( @codedContent, $_ );
        }
    }
    if ($changed)
    {
        open( my $CONFIGFILE, ">$configfileOption" )
          or die "File ($configfileOption) open error: $!";
        print $CONFIGFILE @codedContent;
        close($CONFIGFILE) or die "File ($configfileOption) close error: $!";
    }
}

sub getPassword ()
{
    &msg( "0004D", "getPassword" );
    if ( !defined( $_[0] ) )
    {
        &msg( "0001E", "getPassword" );
        return 1;
    }

    my $password = $_[0];

    if ( $password !~ m/^XOR{/ )
    {
        &msg("0016W");
        return $password;
    }
    $password =~ s/^XOR{//;
    $password =~ s/}$//;
    my $passwordLength = length($password);
    my $cipher         = substr( $cipherKey, 0, $passwordLength );
    my $xor            = $password ^ $cipher;
    &msg( "0005D", "getPassword", 0 );
    return $xor;

}

sub addLineNumbers(@)
{
    &msg( "0004D", "addLineNumbers" );
    if ( !defined(@_) )
    {
        &msg( "0001E", "addLineNumbers" );
        return 1;
    }
    my @array = @_;
    my $i     = 0;
    foreach (@array)
    {
        $array[$i] = ( $i + 1 ) . "\t$array[$i]";
        $i++;
    }
    &msg( "0005D", "addLineNumbers", 0 );
    @LastResult = @array;
    return @array;
}

sub checkDefaults()
{
    &msg( "0004D", "checkDefaults" );

    if ( !defined( $Settings{DEFAULTSERVER} ) )
    {
        &msg( "0021E", "DEFAULTSERVER" );
        exit 1;
    }

    #	$Settings{DEFAULTCOLOR}   = 'GREEN' if (! defined ($Settings{DEFAULTCOLOR})) ;
    $Settings{HEADERCOLOR} = 'WHITE' if ( !defined( $Settings{HEADERCOLOR} ) );
    $Settings{HIGHLIGHTCOLOR} = 'RED'
      if ( !defined( $Settings{HIGHLIGHTCOLOR} ) );
    $Settings{AUTOCONNECT} = 1 if ( !defined( $Settings{AUTOCONNECT} ) );

    if ( !defined( $Settings{EDITOR} ) )
    {
        $Settings{EDITOR} = $OS_win ? "notepad" : "vi";

    }

    if ( !defined( $Settings{TERMINAL} ) )
    {
        $Settings{TERMINAL} = $OS_win ? "cmd" : "xterm";
    }

    if ( -r $Settings{HISTORYFILE} )
    {
        open my $HISTORY, "<", $Settings{HISTORYFILE} or die;
        @History = <$HISTORY>;
        close $HISTORY or die;
        chomp(@History);
        $HistoryPointer = $#History + 1;
    }
    else { $History[0] = ""; $HistoryPointer = $#History + 1; }

    &msg( "0005D", "checkDefaults", 0 );
}

sub readCommand()
{
    if ($OS_win)
    {
        return <STDIN>;
    }
    else
    {
        ReadMode("cbreak");
        my $input = "";
        my @chars;
        my $charPointer = 00;
        while ( push( @chars, ord( ReadKey(0) ) ) )
        {
            if ( $chars[-1] == 65 && $chars[-2] == 91 && $chars[-3] == 27 )
            {    # UP
                next if ( $HistoryPointer <= 0 );
                $HistoryPointer--;
                $input = $History[$HistoryPointer];
                print "\e[2K\r" . "$CurrentPrompt" . "$input";
                $charPointer = length($input);
                open my $DEBUG, ">>", "debug.txt";
                print $DEBUG "length: " . length($input) . ", charPointer: $charPointer\n";
                close($DEBUG);

            }
            elsif ( $chars[-1] == 66 && $chars[-2] == 91 && $chars[-3] == 27 )
            {    # DOWN
                next if ( $HistoryPointer > ( @History - 1 ) );
                $input = "";
                $HistoryPointer++;
                $input = $History[$HistoryPointer]
                  if ( defined $History[$HistoryPointer] );
                print "\e[2K\r" . "$CurrentPrompt" . "$input";
                $charPointer = length($input);
                open my $DEBUG, ">>", "debug.txt";
                print $DEBUG "length: " . length($input) . ", charPointer: $charPointer\n";
                close($DEBUG);

            }
            elsif ( $chars[-1] == 68 && $chars[-2] == 91 && $chars[-3] == 27 )
            {    # LEFT
                next if ( $charPointer <= 0 );
                print "\e[D";
                $charPointer--;
                open my $DEBUG, ">>", "debug.txt";
                print $DEBUG "length: " . length($input) . ", charPointer: $charPointer\n";
                close($DEBUG);

            }
            elsif ( $chars[-1] == 67 && $chars[-2] == 91 && $chars[-3] == 27 )
            {    # RIGHT
                next if ( $charPointer >= length($input) );
                print "\e[C";
                $charPointer++;
                open my $DEBUG, ">>", "debug.txt";
                print $DEBUG "length: " . length($input) . ", charPointer: $charPointer\n";
                close($DEBUG);

            }
            elsif ( $chars[-1] == 127 )
            {    # BACKSPACE
                next if ( $charPointer <= 0 );
                print "\e[D \e[D";
                $charPointer--;
                $input = substr( $input, 0, $charPointer );
                open my $DEBUG, ">>", "debug.txt";
                print $DEBUG "length: " . length($input) . ", charPointer: $charPointer\n";
                close($DEBUG);
            }
            elsif ( $chars[-1] == 80 && $chars[-2] == 79 && $chars[-3] == 27 )
            {    # F1
                print "F1 - HELP \n";
            }
            elsif ( $chars[-1] == 4 )
            {    # CTRL+D
                if ( $input eq "" )
                {
                    ReadMode('normal');
                    print "\n";
                    return "quit";
                }
            }
            elsif (    $chars[-1] == 126
                    && $chars[-2] == 51
                    && $chars[-3] == 91
                    && $chars[-4] == 27 )
            {    # DELETE
                substr( $input, $charPointer, 1, "" );
                print "\e[s\e[2K\r" . "$CurrentPrompt" . "$input\e[u";
            }
            elsif ( $chars[-1] == 1 )
            {    # CTRL-A
                print "CTRL-A\n";
            }
            elsif ( $chars[-1] == 91 && $chars[-2] == 27 )
            {    # OMITT
            }
            elsif ( $chars[-1] == 79 && $chars[-2] == 27 )
            {    # OMITT
            }
            elsif ( $chars[-1] == 51 && $chars[-2] == 91 && $chars[-3] == 27 )
            {    # OMITT
            }
            elsif ( $chars[-1] == 27 )
            {    # ESC
            
                #if ( $input ne "" )
                #{
                #    $input = "";
                #    open DEBUG, ">>", "debug.txt";
                #    print DEBUG "ESClength: " . length($input) . ", charPointer: $charPointer\n";
                #    close(DEBUG);
                #    print "\e[2K\r" . "$Settings{PROMPT}" . "$input";
                #}
            
            }
            elsif ( $chars[-1] == 10 )
            {    # ENTER

                if ( $input =~ m/\w/ )
                {
                    my $command = $input;
                    $HistoryPointer = @History;
                    if ($command ne $History[$HistoryPointer - 1] ) {
                        push( @History, $command );
                    }
                    $HistoryPointer = @History;
                    $input          = "";
                    ReadMode('normal');
                    open my $DEBUG, ">>", "debug.txt";
                    print $DEBUG "length: " . length($input) . ", charPointer: $charPointer\n";
                    close($DEBUG);
                    print "\n";
                    return $command;
                }
                else
                {
                    print "\n" . "$CurrentPrompt";
                }
            }
            else
            {
                if ( $charPointer <= length($input) )
                {
                    substr( $input, $charPointer, 1, chr( $chars[-1] ) );
                    $charPointer++;
                }
                else
                {
                    $input .= chr( $chars[-1] );
                }
                print chr( $chars[-1] );
                open my $DEBUG, ">>", "debug.txt";
                print $DEBUG "length: " . length($input) . ", charPointer: $charPointer\n";
                close($DEBUG);
            }
        }

        ReadMode('normal');
    }

}

1;
